package com.profiloc.util;

import java.util.Vector;

import javax.microedition.location.Criteria;
import javax.microedition.location.Location;
import javax.microedition.location.LocationException;
import javax.microedition.location.LocationListener;
import javax.microedition.location.LocationProvider;
import javax.microedition.location.QualifiedCoordinates;

import net.rim.blackberry.api.phone.Phone;
import net.rim.blackberry.api.phone.PhoneCall;
import net.rim.blackberry.api.phone.PhoneListener;
import net.rim.device.api.system.Alert;
import net.rim.device.api.system.Application;
import net.rim.device.api.system.ApplicationDescriptor;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.system.ApplicationManagerException;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.CodeModuleManager;
import net.rim.device.api.system.EventInjector;
import net.rim.device.api.system.PersistentObject;
import net.rim.device.api.system.PersistentStore;
import net.rim.device.api.system.EventInjector.KeyCodeEvent;
import net.rim.device.api.ui.Keypad;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.Screen;
import net.rim.device.api.ui.Ui;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.UiEngine;
import net.rim.device.api.ui.component.Dialog;

import com.profiloc.model.Profile;
import com.profiloc.ui.screens.GpsLocationScreen;

public class LocationHandler extends Thread implements PhoneListener{

	private GpsLocationScreen screen;
	private boolean update;
	private int interval;
	private static Vector profiles;
	private PersistentObject profilePersist;
	private int index;
	private Profile selected;
	
	private boolean found = false;


	public LocationHandler(GpsLocationScreen screen,boolean update,int interval,int index) {
		// TODO Auto-generated constructor stub
		Phone.addPhoneListener(this);
        profilePersist = PersistentStore.getPersistentObject(0x4e73ce89227e0b61L);

        synchronized (profilePersist) {
        	profiles = (Vector) profilePersist.getContents();
		}
		
		if(screen != null){
			this.screen = screen;
			this.update = false;
			this.index = -1;
		}else{
			this.index = index;
			this.screen = null;
			this.update = update;
			this.interval = interval;
			selected = new Profile();
			selected = (Profile) profiles.elementAt(index);
		}
	}

	public void run() {
		
		/*
		 * new criteria with 50 accuracy 
		 * and also cost is allowed with high power usage
		 * which result with asisted gps location finding
		 */
		
		Criteria criteria = new Criteria();
		criteria.setHorizontalAccuracy(50);
		criteria.setVerticalAccuracy(50);
		criteria.setCostAllowed(true);
		criteria.setPreferredPowerConsumption(Criteria.POWER_USAGE_HIGH);
		
		try {
			
			LocationProvider provider = LocationProvider.getInstance(criteria);

			Location location = provider.getLocation(-1);	
			QualifiedCoordinates qualifiedCoordinates = location.getQualifiedCoordinates();
			
			if(provider != null &&  update == true){
				provider.setLocationListener(new MyLocationListener(), selected.getRefreshTime() * 60 , -1, 10);
			}
			
			if(screen != null){
				screen.setLocation(qualifiedCoordinates.getLatitude(), qualifiedCoordinates.getLongitude());
			}		
			
		} catch (LocationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}
	
	private  class MyLocationListener implements LocationListener{

		public void locationUpdated(LocationProvider provider, Location location) {
			// TODO Auto-generated method stub
			if( selected.getEndTime() == System.currentTimeMillis() ){
				
				/*
				 * check to see if reach the end of the profile time
				 */
				Alert.startVibrate(1500);
				UiApplication.getUiApplication().requestForeground();
			
				synchronized(Application.getEventLock()){   
					
						UiEngine ui = Ui.getUiEngine();
						Screen screen = new Dialog(Dialog.D_OK, "Probably you reached the end of profile time for :\n\""+selected.getName()+"\"\nActivate another one.",
				        Dialog.OK,           Bitmap.getPredefinedBitmap(Bitmap.EXCLAMATION),         Manager.VERTICAL_SCROLL);
						ui.pushGlobalScreen(screen, 1, UiEngine.GLOBAL_QUEUE);
				}
			}

			if (location != null && location.isValid()) {
				found = false;
				Profile temp = new Profile();
				try {
						double lat = location.getQualifiedCoordinates().getLatitude();
						double lon = location.getQualifiedCoordinates().getLongitude();
					
						synchronized(Application.getEventLock()){    
						
							UiEngine ui = Ui.getUiEngine();
							Screen screen = new Dialog(Dialog.D_OK,"Latitude :"+String.valueOf(lat)+" Longitude :"+String.valueOf(lon),
							Dialog.OK,           Bitmap.getPredefinedBitmap(Bitmap.EXCLAMATION),         Manager.VERTICAL_SCROLL);
							ui.pushGlobalScreen(screen, 1, UiEngine.GLOBAL_QUEUE);
						
						}

						for (int i = 0; i < profiles.size(); i++) {
						
							if(index ==i){
								continue;
							}
							
							temp = (Profile) profiles.elementAt(i);
							if(lat == temp.getLatitude() && lon == temp.getLongitude()){
								index = i;
								found = true;
								break;
							}
						}
		     
				if(found){
					
					Alert.startVibrate(1500);
					
					synchronized(Application.getEventLock()){    
						
						UiEngine ui = Ui.getUiEngine();
						Screen screen = new Dialog(Dialog.D_OK, "Your location has changed to:\n\""+temp.getName()+"\"\nChange your profile sound",
				        Dialog.OK,           Bitmap.getPredefinedBitmap(Bitmap.EXCLAMATION),         Manager.VERTICAL_SCROLL);
						ui.pushGlobalScreen(screen, 1, UiEngine.GLOBAL_QUEUE);
						
					}

					int handle = CodeModuleManager.getModuleHandle("net_rim_bb_profiles_app");
		    		ApplicationDescriptor[] appDescr = CodeModuleManager.getApplicationDescriptors(handle);
		    		if (appDescr.length > 0) {
		    			try {
		    		    ApplicationManager.getApplicationManager().runApplication(
		    		      appDescr[0]);
		    		   	} catch (ApplicationManagerException e) {
		    		    // TODO Auto-generated catch block
		    		    e.printStackTrace();
		    		   	}
		    		}
				}
					
					
		     }catch (Exception e) {
		    	 
		         e.printStackTrace();
		     }
		     
		   }
	}

		public void providerStateChanged(LocationProvider provider, int newState) {
			// TODO Auto-generated method stub
		   if (newState == LocationProvider.TEMPORARILY_UNAVAILABLE){
				provider.reset();
	        }
	       if (newState == LocationProvider.OUT_OF_SERVICE){
	    	   provider.reset();
	       	}
		}		
	}

	public void callAdded(int callId) {
		// TODO Auto-generated method stub
		
	}

	public void callAnswered(int callId) {
		// TODO Auto-generated method stub
		
	}

	public void callConferenceCallEstablished(int callId) {
		// TODO Auto-generated method stub
		
	}

	public void callConnected(int callId) {
		// TODO Auto-generated method stub
		
	}

	public void callDirectConnectConnected(int callId) {
		// TODO Auto-generated method stub
		
	}

	public void callDirectConnectDisconnected(int callId) {
		// TODO Auto-generated method stub
		
	}

	public void callDisconnected(int callId) {
		// TODO Auto-generated method stub
		
	}

	public void callEndedByUser(int callId) {
		// TODO Auto-generated method stub
		
	}

	public void callFailed(int callId, int reason) {
		// TODO Auto-generated method stub
		
	}

	public void callHeld(int callId) {
		// TODO Auto-generated method stub
		
	}

	public void callIncoming(int callId) {
		// TODO Auto-generated method stub

		/*
		 * reject call if user select it to reject
		 */
		
		if(!selected.getAcceptCalls()){
			final PhoneCall call = Phone.getCall(callId);  
	        final String number = call.getDisplayPhoneNumber();  
	         System.out.println(number);  
	         EventInjector.KeyCodeEvent pressEndKey = new EventInjector.KeyCodeEvent(  
	                 KeyCodeEvent.KEY_DOWN, (char) Keypad.KEY_END, 0);  
	        EventInjector.KeyCodeEvent releaseEndKey = new EventInjector.KeyCodeEvent(  
	                KeyCodeEvent.KEY_UP, (char) Keypad.KEY_END, 0);  
	   
	         try {  
	             Thread.sleep(1000);  
	         } catch (InterruptedException e) {  
	             // TODO Auto-generated catch block  
	         e.printStackTrace();  
	         }  
	         EventInjector.invokeEvent(pressEndKey);  
	         EventInjector.invokeEvent(releaseEndKey);
		}
		
	}

	public void callInitiated(int callid) {
		// TODO Auto-generated method stub

	}

	public void callRemoved(int callId) {
		// TODO Auto-generated method stub
		
	}

	public void callResumed(int callId) {
		// TODO Auto-generated method stub
		
	}

	public void callWaiting(int callid) {
		// TODO Auto-generated method stub
		
	}

	public void conferenceCallDisconnected(int callId) {
		// TODO Auto-generated method stub
		
	}


}
